#ifndef NR_SCHEDULER_H
#define NR_SCHEDULER_H

#include "nr_object.h"

class nr_scheduler : public nr_object
{
public:
    typedef enum nr_scheduler_type_enum
    {
        NR_SCHEDULER_TYPE_NONE = 0,
        NR_SCHEDULER_TYPE_NORMAL,
        NR_SCHEDULER_TYPE_CLOCK,
        NR_SCHEDULER_TYPE_DAILY,
        NR_SCHEDULER_TYPE_WEEKLY,
    } nr_scheduler_type_t;
    
    nr_scheduler() : m_is_active(false)
    {
    }
    
    nr_scheduler(nr_scheduler_type_t type) 
        : m_type(type)
        , m_is_active(false)
    {
    }

    ~nr_scheduler() { }
     
    nr_scheduler_type_t type() { m_type; }

    QString& name() { return m_name; };

    virtual void set_active(bool active)
    {
        m_is_active = active;
    }

    bool is_active() { m_is_active; }

    // Check current scheduler 
    // Return true means it should be in record state
    // Return false means it should not be in record state
    virtual bool check_scheduler() = 0;

protected:
    nr_scheduler_type_t m_type;
    QString m_name;
    bool m_is_active;
};

/** Normal scheduler  
 *  Only contains two states : on or off
 *  When state on, the record will last for ever
 *  When state off, the record will be stopped
 */
class nr_scheduler_normal : public nr_scheduler
{
public:
    nr_scheduler_normal() 
        : nr_scheduler(NR_SCHEDULER_TYPE_NORMAL)
        , m_state(false) 
    {
    }
    
    nr_scheduler_normal(bool init_state)
        : nr_scheduler(NR_SCHEDULER_TYPE_NORMAL)
        , m_state(init_state) 
    {
    }
    
    virtual ~nr_scheduler_normal() { }

    virtual void set_active(bool active)
    {
        nr_scheduler::set_active(active);
    }

    // Check current scheduler 
    // Return true means it should be in record state
    // Return false means it should no be in record state
    virtual bool check_scheduler() { return m_state; }
    
    void set_state(bool on);
    
    bool state();

private:
    bool m_state;
};

/** Clock scheduler, it occurred only once
 *  It contains at start time and end time
 *  The record will start at the start time and end at the end time
 */
class nr_scheduler_clock : public nr_scheduler
{
public:
    nr_scheduler_clock() 
        : nr_scheduler(NR_SCHEDULER_TYPE_CLOCK)
    { 
    }

    ~nr_scheduler_clock() { }

    virtual void set_active(bool active)
    {
        m_is_active = active;
    }

    void set_clock(const QDateTime& start_time, const QDateTime& end_time)
    {
        m_start_time = start_time;
        m_end_time = end_time;
    }
        
    // Check current scheduler 
    // Return true means it should be in record state
    // Return false means it should no be in record state
    virtual bool check_scheduler() ;
    
    const QDateTime& start_time() { return m_start_time; }

    const QDateTime& end_time() { return m_end_time; }

private:
    QDateTime m_start_time, m_end_time;
};

/** 
 * Daily scheduler, repeat day by day
 */
class nr_scheduler_daily : public nr_scheduler
{
public:
    typedef struct nr_scheduler_period
    {
        QTime begin_time;
        QTime end_time;
    } nr_scheduler_period_t;
    
    nr_scheduler_daily() 
        : nr_scheduler(NR_SCHEDULER_TYPE_DAILY)
    {
    }
    
    ~nr_scheduler_daily() { }
    
    bool add_time(QTime begin_time, QTime end_time) { return false; }

    nr_error_t check_valid(QTime begin_time, QTime end_time);
    
    // Check current scheduler 
    // Return true means it should be in record state
    // Return false means it should no be in record state
    virtual bool check_scheduler();
    
private:
    QList<nr_scheduler_period_t> m_periods;
};

/** 
 * Weekly scheduler, repeat week by week
 */
class nr_scheduler_weekly : public nr_scheduler
{
public:
    typedef enum nr_week_day_enum
    {
        SUNDAY = 0,
        MONDAY = 1,
        TUESDAY = 2,
        WEDNESDAY = 3,
        THURSDAY = 4,
        FRIDAY = 5,
        SATURDAY = 6,
    }nr_week_day_t;

    typedef struct nr_scheduler_week_period
    {
        nr_week_day_t begin_day;
        QTime begin_time;
        nr_week_day_t end_day;
        QTime end_time;
    } nr_scheduler_week_period_t;

    nr_scheduler_weekly() 
        : nr_scheduler(NR_SCHEDULER_TYPE_WEEKLY)
    {
    }
    
    ~nr_scheduler_weekly() { }

    bool add_time(nr_week_day_t begin_day, QTime begin_time, nr_week_day_t end_day, QTime end_time) { return false; }
    
    nr_error_t check_valid(nr_week_day_t begin_day, QTime begin_time, nr_week_day_t end_day, QTime end_time);

    // Check current scheduler 
    // Return true means it should be in record state
    // Return false means it should no be in record state
    virtual bool check_scheduler();

private:
    QList<nr_scheduler_week_period_t> m_periods;
};

typedef QHash<QString, nr_scheduler*> nr_schedulers;

#endif // NR_SCHEDULER_H
